package com.polaris.live.widget.avatar

import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.widget.FrameLayout
import androidx.appcompat.widget.AppCompatImageView
import com.bumptech.glide.Glide
import com.polaris.live.common.manager.CoroutineScopeManager
import com.polaris.live.resp.bean.FrameImageBean
import com.polaris.live.utils.file.FileUtils
import com.polaris.live.utils.image.ImageUtils
import com.polaris.live.utils.viewscope.autoDisposeScope
import com.polaris.live.widget.bubble.DownLoadFileUtil
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.libpag.PAGFile
import org.libpag.PAGImageView
import java.io.File
import kotlin.math.max
import kotlin.math.min

/**
 * 头像框控件
 * @author Created by 天晴 on 2024/1/17 15:12
 * @since 1.0.0
 **/
class AvatarFrameView(context: Context, attrs: AttributeSet?) : FrameLayout(context, attrs) {

    private var parentWidth: Int = 0   //当前控件宽
    private var parentHeight: Int = 0  //当前控件高
    private var childWidth: Int = 0    //子控件宽 -- 设置的头像
    private var childHeight: Int = 0   //子控件高 -- 设置的头像
    private var frameWidth: Int = 0    //子控件宽 -- 头像框
    private var frameHeight: Int = 0   //子控件高 -- 头像框
    private var mFrameImageBean: FrameImageBean? = null
    private var mImage: AppCompatImageView? = null
    private var mGiftPag: PAGImageView? = null
    private var back: ((Int, Int, Int) -> Unit)? = null

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        mFrameImageBean?.run {
            val widthMode = MeasureSpec.getMode(widthMeasureSpec)
            val widthSize = MeasureSpec.getSize(widthMeasureSpec)
            val heightMode = MeasureSpec.getMode(heightMeasureSpec)
            val heightSize = MeasureSpec.getSize(heightMeasureSpec)
            // 测量子视图
            (0 until childCount).forEach { i ->
                getChildAt(i)?.let { child ->
                    measureChild(child, widthMeasureSpec, heightMeasureSpec)
                    childWidth = max(childWidth, child.measuredWidth)
                    childHeight = max(childHeight, child.measuredHeight)
                }
            }
            //子view控件最大范围
            if (childWidth != childHeight) {
                childWidth = min(childWidth, childHeight)
                childHeight = childWidth
            }
            //根据比例缩放边距
            val roaW = childWidth / (imageWidth - left - right).toDouble()
            val l = (left * roaW).toInt()
            val r = (right * roaW).toInt()
            val roaH = childHeight / (imageHeight - top - bottom).toDouble()
            val t = (top * roaH).toInt()
            val b = (bottom * roaH).toInt()
            //获取父控件最大宽
            parentWidth = when (widthMode) {
                MeasureSpec.UNSPECIFIED -> childWidth + l + r
                MeasureSpec.AT_MOST -> min(widthSize, childWidth + l + r)
                MeasureSpec.EXACTLY -> widthSize
                else -> childWidth + l + r
            }
            //获取父控件最大高
            parentHeight = when (heightMode) {
                MeasureSpec.UNSPECIFIED -> childHeight + t + b
                MeasureSpec.AT_MOST -> min(heightSize, childHeight + t + b)
                MeasureSpec.EXACTLY -> heightSize
                else -> childHeight + t + b
            }
            //计算长宽比
            val ratio = (imageWidth).toFloat() / (imageHeight)
            //当前长宽比
            val nRatio = parentWidth.toFloat() / parentHeight
            //縮放為适合的服务器指定的比例
            if (ratio > nRatio) {
                parentHeight = (parentWidth / ratio).toInt()
            } else if (ratio < nRatio) {
                parentWidth = (parentHeight / ratio).toInt()
            }
            frameWidth = parentWidth
            frameHeight = parentHeight
            setMeasuredDimension(parentWidth, parentHeight)
            measureChildren(widthMeasureSpec, heightMeasureSpec)
        }
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        var bottomHeight = 0
        mFrameImageBean?.let { frame ->
            for (i in 0 until childCount) {
                val child: View = getChildAt(i)
                if (child == mImage || child == mGiftPag) {
                    child.layout(0, 0, frameWidth, frameHeight)
                } else {
                    //实际边数据
                    val roaW2 = parentWidth / frame.imageWidth.toDouble()
                    val roaH2 = parentHeight / frame.imageHeight.toDouble()
                    val ll = (frame.left * roaW2).toInt()
                    val rr = (frame.right * roaW2).toInt()
                    val tt = (frame.top * roaH2).toInt()
                    val bb = (frame.bottom * roaH2).toInt()
                    bottomHeight = bb
                    child.layout(
                        ll,
                        tt,
                        frameWidth - rr,
                        frameHeight - bb
                    )
                }
            }
        } ?: super.onLayout(changed, l, t, r, b)
        back?.invoke(width, height, bottomHeight)
    }

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()

        mGiftPag?.run {
            if (!this.isPlaying) {
                play()
            }
        }
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()

        mGiftPag?.run {
            if (this.isPlaying) {
                pause()
            }
        }
    }

    /**
     * 设置头像框
     */
    fun setFrameString(avatarFrame: String?) {
        val bean = FrameImageUtils.urlToFrameImageBean(avatarFrame)
        setFrameImage(bean)
    }

    /**
     * 设置头像框
     */
    fun setFrameImage(bean: FrameImageBean?) {
        if (bean == null) {
            clearLastFrame()
            requestLayout()
            invalidate()
            return
        }
        if (mFrameImageBean?.isSameAs(bean) == true) {
            return
        }
        clearLastFrame()
        mFrameImageBean = bean
        if (bean.isNet) {
            if (bean.isPag) {
                showPag(bean)
            } else {
                addImageView(bean.addTop)
                mImage?.let {
                    Glide.with(context)
                        .load(ImageUtils.imgPath(bean.netUrl))
                        .into(it)
                }
            }
        } else {
            if (bean.isPag) {
                addPagView(bean.addTop)
                playPag(bean.drawablePath)
            } else {
                addImageView(bean.addTop)
                mImage?.setImageResource(bean.drawableId)
            }
        }
        requestLayout()
        invalidate()
    }

    private fun showPag(bean: FrameImageBean) {
        val pathDir = FileUtils.getPagFile()
        val filePath = FileUtils.getFilePath(pathDir, bean.netUrl)
        if (File(filePath).exists()) {
            addPagView(bean.addTop)
            playPag(filePath)
            return
        }
        autoDisposeScope.launch {
            DownLoadFileUtil.getPagPath(bean.netUrl)?.let { path ->
                withContext(CoroutineScopeManager.mainDispatcher) {
                    if (bean.netUrl != mFrameImageBean?.netUrl) return@withContext
                    addPagView(bean.addTop)
                    playPag(path)
                }
            }

        }
    }

    private fun playPag(path: String) {
        mGiftPag?.apply {
            setRepeatCount(-1)
            composition = PAGFile.Load(path)
            play()
        }
    }

    private fun clearLastFrame() {
        mImage?.let {
            removeView(it)
        }
        mGiftPag?.let {
            removeView(it)
        }
        parentWidth = 0
        parentHeight = 0
        childWidth = 0
        childHeight = 0
        frameWidth = 0
        frameHeight = 0
        mFrameImageBean = null
        mImage = null
        mGiftPag = null
    }

    /**
     * 刷新控件大小后回调
     */
    fun setFrameImageCompleted(back: (parentWidth: Int, parentHeight: Int, bottomHeight: Int) -> Unit) {
        this.back = back
    }

    /**
     * 判断是否是同一个数据
     */
    private fun FrameImageBean.isSameAs(other: FrameImageBean): Boolean {
        if (isNet && other.isNet && netUrl == other.netUrl) {
            return true
        }
        if (!isNet && !other.isNet && drawableId == other.drawableId) {
            return true
        }
        return false
    }

    /**
     * 添加静态头像
     */
    private fun addImageView(isTop: Boolean) {
        mImage?.let { removeView(it) }
        mImage = AppCompatImageView(context)
        mImage?.layoutParams = LayoutParams(0, 0)
        if (isTop) {
            addView(mImage)

        } else {
            addView(mImage, 0)
        }
    }

    /**
     * 添加动态头像
     */
    private fun addPagView(isTop: Boolean) {
        mGiftPag?.let { removeView(it) }
        mGiftPag = PAGImageView(context)
        mGiftPag?.layoutParams = LayoutParams(0, 0)
        if (isTop) {
            addView(mGiftPag)
        } else {
            addView(mGiftPag, 0)
        }
    }
}